// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "Camera/LyraCameraAssistInterface.h"
#include "CommonPlayerController.h"
#include "Teams/LyraTeamAgentInterface.h"

#include "LyraPlayerController.generated.h"

#define UE_API LYRAGAME_API

struct FGenericTeamId;

class ALyraHUD;
class ALyraPlayerState;
class APawn;
class APlayerState;
class FPrimitiveComponentId;
class IInputInterface;
class ULyraAbilitySystemComponent;
class ULyraSettingsShared;
class UObject;
class UPlayer;
struct FFrame;

/**
 * ALyraPlayerController
 *
 *	该项目使用的基础玩家控制器类。
 */
UCLASS(MinimalAPI, Config = Game, Meta = (ShortTooltip = "该项目使用的基础玩家控制器类。"))
class ALyraPlayerController : public ACommonPlayerController, public ILyraCameraAssistInterface, public ILyraTeamAgentInterface
{
	GENERATED_BODY()

public:

	UE_API ALyraPlayerController(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());

	/**
	 * 获取Lyra玩家状态。
	 */
	UFUNCTION(BlueprintCallable, Category = "Lyra|PlayerController")
	UE_API ALyraPlayerState* GetLyraPlayerState() const;

	/**
	 * 获取Lyra技能系统组件。
	 */
	UFUNCTION(BlueprintCallable, Category = "Lyra|PlayerController")
	UE_API ULyraAbilitySystemComponent* GetLyraAbilitySystemComponent() const;

	/**
	 * 获取Lyra HUD。
	 */
	UFUNCTION(BlueprintCallable, Category = "Lyra|PlayerController")
	UE_API ALyraHUD* GetLyraHUD() const;

	/**
	 * 尝试录制客户端回放。
	 */
	UFUNCTION(BlueprintCallable, Category = "Lyra|PlayerController")
	UE_API bool TryToRecordClientReplay();

	/**
	 * 是否应该录制客户端回放。
	 */
	UE_API virtual bool ShouldRecordClientReplay();

	/**
	 * 在服务器上运行作弊命令。
	 */
	UFUNCTION(Reliable, Server, WithValidation)
	UE_API void ServerCheat(const FString& Msg);

	/**
	 * 在服务器上为所有玩家运行作弊命令。
	 */
	UFUNCTION(Reliable, Server, WithValidation)
	UE_API void ServerCheatAll(const FString& Msg);

	//~AActor接口
	UE_API virtual void PreInitializeComponents() override; // 预初始化组件
	UE_API virtual void BeginPlay() override; // 开始游戏
	UE_API virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; // 结束游戏
	UE_API virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override; // 获取生命周期复制属性
	//~End of AActor接口

	//~AController接口
	UE_API virtual void OnPossess(APawn* InPawn) override; // 控制角色
	UE_API virtual void OnUnPossess() override; // 取消控制
	UE_API virtual void InitPlayerState() override; // 初始化玩家状态
	UE_API virtual void CleanupPlayerState() override; // 清理玩家状态
	UE_API virtual void OnRep_PlayerState() override; // 玩家状态复制回调
	//~End of AController接口

	//~APlayerController接口
	UE_API virtual void ReceivedPlayer() override; // 接收玩家
	UE_API virtual void PlayerTick(float DeltaTime) override; // 玩家每帧调用
	UE_API virtual void SetPlayer(UPlayer* InPlayer) override; // 设置玩家
	UE_API virtual void AddCheats(bool bForce) override; // 添加作弊功能
	UE_API virtual void UpdateForceFeedback(IInputInterface* InputInterface, const int32 ControllerId) override; // 更新力反馈
	UE_API virtual void UpdateHiddenComponents(const FVector& ViewLocation, TSet<FPrimitiveComponentId>& OutHiddenComponents) override; // 更新隐藏组件
	UE_API virtual void PreProcessInput(const float DeltaTime, const bool bGamePaused) override; // 预处理输入
	UE_API virtual void PostProcessInput(const float DeltaTime, const bool bGamePaused) override; // 后处理输入
	//~End of APlayerController接口

	//~ILyraCameraAssistInterface接口
	UE_API virtual void OnCameraPenetratingTarget() override; // 摄像机穿透目标时调用
	//~End of ILyraCameraAssistInterface接口
	
	//~ILyraTeamAgentInterface接口
	UE_API virtual void SetGenericTeamId(const FGenericTeamId& NewTeamID) override; // 设置通用队伍ID
	UE_API virtual FGenericTeamId GetGenericTeamId() const override; // 获取通用队伍ID
	UE_API virtual FOnLyraTeamIndexChangedDelegate* GetOnTeamIndexChangedDelegate() override; // 获取队伍索引改变委托
	//~End of ILyraTeamAgentInterface接口

	/**
	 * 设置是否自动运行。
	 */
	UFUNCTION(BlueprintCallable, Category = "Lyra|Character")
	UE_API void SetIsAutoRunning(const bool bEnabled);

	/**
	 * 获取是否自动运行。
	 */
	UFUNCTION(BlueprintCallable, Category = "Lyra|Character")
	UE_API bool GetIsAutoRunning() const;

private:
	UPROPERTY()
	FOnLyraTeamIndexChangedDelegate OnTeamChangedDelegate; // 队伍改变委托

	UPROPERTY()
	TObjectPtr<APlayerState> LastSeenPlayerState; // 最后看到的玩家状态

private:
	/**
	 * 玩家状态队伍改变回调。
	 */
	UFUNCTION()
	void OnPlayerStateChangedTeam(UObject* TeamAgent, int32 OldTeam, int32 NewTeam);

protected:
	/**
	 * 玩家状态改变回调。
	 */
	UE_API virtual void OnPlayerStateChanged();

private:
	/**
	 * 广播玩家状态改变。
	 */
	void BroadcastOnPlayerStateChanged();

protected:

	//~APlayerController接口

	//~End of APlayerController接口

	/**
	 * 设置改变回调。
	 */
	UE_API void OnSettingsChanged(ULyraSettingsShared* Settings);
	
	/**
	 * 开始自动运行。
	 */
	UE_API void OnStartAutoRun();
	
	/**
	 * 结束自动运行。
	 */
	UE_API void OnEndAutoRun();

	/**
	 * 蓝图可实现的开始自动运行事件。
	 */
	UFUNCTION(BlueprintImplementableEvent, meta=(DisplayName="OnStartAutoRun"))
	UE_API void K2_OnStartAutoRun();

	/**
	 * 蓝图可实现的结束自动运行事件。
	 */
	UFUNCTION(BlueprintImplementableEvent, meta=(DisplayName="OnEndAutoRun"))
	UE_API void K2_OnEndAutoRun();

	bool bHideViewTargetPawnNextFrame = false; // 下一帧隐藏视图目标角色
};


// 用于回放捕获和播放的玩家控制器
UCLASS()
class ALyraReplayPlayerController : public ALyraPlayerController
{
	GENERATED_BODY()

	/**
	 * 回放玩家控制器每帧调用。
	 */
	virtual void Tick(float DeltaSeconds) override;
	
	/**
	 * 平滑目标视图旋转。
	 */
	virtual void SmoothTargetViewRotation(APawn* TargetPawn, float DeltaSeconds) override;
	
	/**
	 * 是否应该录制客户端回放。
	 */
	virtual bool ShouldRecordClientReplay() override;

	/**
	 * 录制者玩家状态更新回调。
	 */
	void RecorderPlayerStateUpdated(APlayerState* NewRecorderPlayerState);

	/**
	 * 玩家状态角色设置回调。
	 */
	UFUNCTION()
	void OnPlayerStatePawnSet(APlayerState* ChangedPlayerState, APawn* NewPlayerPawn, APawn* OldPlayerPawn);

	// 我们当前正在跟随的玩家状态 */
	UPROPERTY(Transient)
	TObjectPtr<APlayerState> FollowedPlayerState; // 被跟随的玩家状态
};

#undef UE_API